/*
 * ﻿Copyright (C) 2012-2013 NewMain Softech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.newmainsoftech.ant.taskdefs.maven;

import java.io.File;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;

import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
import org.apache.maven.settings.building.SettingsBuilder;
import org.apache.maven.settings.building.SettingsBuildingRequest;
import org.apache.maven.settings.building.SettingsBuildingResult;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Property;
import org.apache.tools.ant.types.LogLevel;
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
import org.sonatype.plexus.components.cipher.PlexusCipher;
import org.sonatype.plexus.components.cipher.PlexusCipherException;
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;

import com.newmainsoftech.ant.MavenProjectAccessor;
import com.newmainsoftech.ant.types.maven.MavenPath;

/**
 * Extension of Ant's Property task <b>to read server credential information from <code>servers</code> 
 * element of Maven settings file and store user name and decrypted password to Maven properties 
 * (and Ant properties.)</b><br />
 * Though Maven provides <a href="https://maven.apache.org/guides/mini/guide-encryption.html"
 * >password encryption feature</a>, sometime there are places in plugin configuration where plugin 
 * does not support reading credential information from Maven settings file; one place of such is   
 * JNDI/JDBC configuration with container plugin like cargo-maven2-plugin, maven-glassfish-plugin and  
 * maven-embedded-glassfish-plugin, in spite of that sql-maven-plugin uses Maven's password encryption 
 * feature. And it is obviously preferable to avoid having password in clear text in such configuration 
 * section of container plugin in pom.xml what may be distributed out of own hands. Other plugin with 
 * what this can be useful is the maven-gpg-plugin; with what many users seem to have been providing 
 * their private key passphrase for signing artifact binary like <code>-Darguments="-Dgpp.passphrase=XXX"
 * </code> in clear text at command line. This may help to replace such clear text to expression of 
 * property (what will be read and decrypted from server section of Maven settings file on the fly) 
 * in the pom.xml. <br />
 * Additionally to usage in manve-antrun-plugin's <code>execution</code> tag, this can also be used in 
 * stand-alone Ant environment. <br />
 * For decryption, currently supporting only usage of the password element of the server element but 
 * usage of the privateKey and passphrase elements of the server element in Maven settings file.<br /> 
 * 
 * <h4><a id="usage">Example of usage as <code>mvnservercreden</code> Ant task tag</a></h4>
 * <b>Use <code>mvnservercreden</code> tag in Ant's <code>target</code> tag</b> (what can be defined <b>in 
 * <code>configuration</code> tag of manve-antrun-plugin's <code>execution</code> tag</b> as well 
 * as in an Ant file).
 * <ul>
 *  <li><b>To read user name and password for test_ds1 server element</b> from default Maven settings file 
 *  	(default to ${user.home}/.m2/settings.xml and ${M2_HOME}/conf/settins.xml) and <b>store user name 
 *  	and decrypted password to test_ds1.username and test_ds1.password Maven properties</b> (as well 
 *  	as Ant properties): 
 *  	<blockquote><code>
 *  		&lt;<b>mvnservercreden serverid</b>="test_ds1" /&gt;
 *  	</code></blockquote>
 *  	<ul>
 *  	 <li><b>serverid</b> : <b>to specify server ID found in &lt;servers&gt; element of Maven's 
 *  		global or user settings file</b>.
 *  	 </li>
 *  	</ul>
 *  	<br />
 *  	Then, at cargo-maven2-plugin configuration in Maven's pom.xml, you may use those 
 *  	in JNDI/JDBC configuration:
 *  	<blockquote><code>
 *  		&lt;<b>plugin</b>&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;groupId&gt;org.codehaus.cargo&lt;/groupId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>artifactId</b>&gt;<b>cargo-maven2-plugin</b>&lt;/artifactId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>configuration</b>&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;container&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;containerId&gt;glassfish3x&lt;/containerId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;artifactInstaller&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;groupId&gt;org.glassfish.main.distributions&lt;/groupId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;artifactId&gt;glassfish&lt;/artifactId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;/artifactInstaller&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;/container&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;configuration&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;type&gt;standalone&lt;/type&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;properties&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;cargo.glassfish.domain.name&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${project.artifactId}_domain<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;/cargo.glassfish.domain.name&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;cargo.servlet.port&gt;8080&lt;/cargo.servlet.port&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;cargo.datasource.datasource.test_ds1&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;cargo.datasource.jndi=jdbc/test_ds1|<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;cargo.datasource.url=jdbc:mysql://localhost:3306/test_ds1|<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;cargo.datasource.driver=com.mysql.jdbc.jdbc2.optional.MysqlDataSource|<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;<b>cargo.datasource.username</b>=<b>${test_ds1.username}</b>|<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;<b>cargo.datasource.password</b>=<b>${test_ds1.passowrd}</b><br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;/cargo.datasource.datasource.test_ds1&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;/properties&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;/configuration&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;
 *  		&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;/configuration&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  		&lt;/plugin&gt;<br />
 *  	</code></blockquote>
 *  	So, <b>no user name and password in clear text in your pom.xml</b>.<br />
 *  	<br />
 *  </li>
 *  <li><b>To explicitly specify name of properties</b>:<br />
 *  	By default, this (<code>&lt;mvnservercreden&gt;</code> Ant task) uses specified server ID as 
 *  	prefix of property name for user name and password. If you like to use unique name of property 
 *  	to store user name and/or password, then use either one of the following ways:   
 *  	<ul>
 *  	 <li>Use <b>name attribute</b>: 
 *  		<blockquote><code>
 *  			&lt;mvnservercreden serverid="test_ds1" <b>name</b>="<b>ds1_conf</b>" /&gt;<br />
 *  		</code></blockquote>
 *  		That will <b>store user name and password</b> from test_ds1 server element in Maven 
 *  		settings file <b>to ds1_conf.username and ds1_conf.password Maven property</b>.<br />
 *  		<br />
 *  	 </li>
 *  	 <li>Use <b>userpropname</b> and/or <b>passwordpropname</b> attributes:
 *  		<blockquote><code>
 *  			&lt;mvnservercreden serverid="test_ds1" <br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;<b>userpropname</b>="<b>ds1_user</b>"<br /> 
 *  			&nbsp;&nbsp;&nbsp;&nbsp;<b>passwordpropname</b>="<b>ds1_password</b>" /&gt;<br />
 *  		</code></blockquote>
 *  		That will <b>store user name and password</b> from test_ds1 server element in Maven 
 *  		settings file <b>to ds1_user and ds1_password Maven property</b>.<br />
 *  		<br />
 *  		One of the <b>practical usages in this way is with maven-gpg-plugin</b>: 
 *  		<ol>
 *  		 <li>In Maven user settings file (default to ${user.home}/.m2/settings.xml), add a server 
 *  			element with encrypted gpg private key passphrase:<br />
 *  			<blockquote><code>
 *    			&lt;<b>server</b>&gt;<br />
 *    			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>id</b>&gt;<b>gpg_passphrase</b>&lt;/id&gt;<br />
 *    			&nbsp;&nbsp;&nbsp;&nbsp;&lt;password&gt;{***_will_be_a_emcrypted_password_here_***}&lt;/password&gt;<br />
 *    			&lt;/server&gt;<br />
 *  			</blockquote></code>
 *  		 </li>
 *  		 <li>In your project pom.xml file, <b>add the maven-gpg-plugin</b>, and, by refering 
 *  			the <a href="#configuration">Configuration</a> section later in this document, 
 *  			<b>add the maven-antrun-plugin</b>; 
 *  			in the configuration of maven-antrun-plugin (under release profile), have a mvnservercreden 
 *  			statement like:   
 *  			<blockquote><code>
 *  			&lt;plugin&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>groupId</b>&gt;<b>org.apache.maven.plugins</b>&lt;/groupId&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>artifactId</b>&gt;<b>maven-antrun-plugin</b>&lt;/artifactId&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;executions&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>execution</b>&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;id&gt;set_gpg_prop_execution&lt;/id&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;phase&gt;post-integration-test&lt;/phase&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;goals&gt;&lt;goal&gt;run&lt;/goal&gt;&lt;/goals&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>configuration</b>&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>target</b> name="set_gpg_prop_target"&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>taskdef<br /> 
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;resource="net/sf/antcontrib/antlib.xml"<br /> 
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;classpathref="maven.plugin.classpath"</b> /&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>mvnservercreden<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;serverid="gpg_passphrase" <br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;passwordpropname="gpg.passphrase"</b> /&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/configuration&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/execution&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;
 *  			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/executions&gt;<br />
 *  			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  			&lt;/plugin&gt;<br />
 *  			</blockquote></code>
 *  			By something like above, the private key passphrase for signing artifact binary will be 
 *  			read from Maven user setting file, decrypted, and assigned to the <code>gpg.passphrase</code> 
 *  			property. Hence, does <b>not need to provide the passphrase in clear text at neither of 
 *  			command line nor property section of pom.xml in order to feed it to maven-gpg-plugin</b>. 
 *  		 </li>
 *  		 <li><b>Execute the perform goal of maven-release-plugin with --batch-mode option</b>; so that 
 *  			maven-gpg-plugin does not prompt for entering password.
 *  			<blockquote><code>
 *  			<b>mvn --batch-mode</b> release:clean release:prepare <b>release:perform</b>
 *  			</code></blockquote>
 *  		 </li>
 *  		</ol>
 *  	 </li>
 *  	</ul>
 *  	<br />
 *  </li>
 *  <li><b>To specify custom Maven settings file(s)</b>:<br />
 *  	<ul>
 *  	 <li>For use with maven-antrun-plugin, use regular options of mvn command line tool:
 *  		<ul>
 *  		 <li>-s or --settings for Maven user settings file</li>
 *  		 <li>-gs or --global-settings for Maven global settings file</li>
 *  		</ul> 
 *  		Note: please check for the <a href="#limitation">Limitation/restriction/prerequisite</a> 
 *  		section below too.
 *  	 </li>
 *  	 <li>Use attributes of <code>&lt;mvnservercreden&gt;</code> Ant task
 *  		<blockquote><code>
 *  		&lt;mvnservercreden serverid="test_ds1" <br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;<b>settingssecuritypath</b>="/my/custom/maven/settings/settings-security.xml" <br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;<b>globalsettingspath</b>="/my/custom/maven/settings/global_settings.xml"<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;<b>usersettingspath</b>="/my/custom/maven/settings/user_settings.xml" /&gt;
 *  		</code></blockquote>
 *  		<ul>
 *  		 <li><b>settingssecuritypath</b> : to provide location of specific Maven 
 *  			settings-security.xml file. <br />
 *  			<b>Default to ${user.home}/.m2/settings-security.xml</b> file.
 *  		 </li>
 *  		 <li><b>globalsettingspath</b> : to provide location of specific Maven global 
 *  			settings.xml file. <br />
 *  			<b>Default to ${M2_HOME}/conf/settins.xml</b> file.
 *  		 </li>
 *  		 <li><b>usersettingspath</b> : to provide location of specific Maven user 
 *  			settings.xml file. <br />
 *  			<b>Default to ${user.home}/.m2/settings.xml</b> file.<br />
 *  			<ul>
 *  			 <li>Note for maven-release-plugin: <br />
 *  				For use with maven-release-plugin and you need to specify custom user settings file 
 *  				other than default one with <code>usersettingspath</code> attribute of 
 *  				<code>&lt;mvnservercreden&gt;</code> Ant task, then use one of following ways with 
 *  				using <code>usersettingspath</code> attribute:
 *  				<ul>
 *  				 <li>Set true to <code>ignorecmdargs</code> attribute of <code>&lt;mvnservercreden&gt;</code> Ant task
 *  					<blockquote><code>
 *  					&lt;mvnservercreden <b>ignorecmdargs="true"</b> <br />
 *  					&nbsp;&nbsp;&nbsp;&nbsp;usersettingspath="/my/custom/maven/settings/user_settings.xml"<br />
 *  					&nbsp;&nbsp;&nbsp;&nbsp;... / &gt;
 *  					</code></blockquote>
 *  				 </li>
 *  				 <li>Set true to mvnservercreden.ignorecmdargs property at command line
 *  					<blockquote><code>
 *  					mvn <b>-Darguments="-Dmvnservercreden.ignorecmdargs=true"</b> release:clean release:prepare release:perform
 *  					</code></blockquote>
 *  				 </li>
 *  				</ul>
 *  				Background description: maven-release-plugin generates user settings file on the fly 
 *  				and automatically specify it with -s option of mvn command line tool to use it during 
 *  				build in spawned shell command. Because this (<code>&lt;mvnservercreden&gt;</code> Ant 
 *  				task) puts precedence either -s or --settings option of mvn command line tool over 
 *  				the <code>usersettingspath</code> attribute by default, it fails to find appropriate 
 *  				server element for targeted server ID from custom user settings file (other than 
 *  				default one) specified with the <code>usersettingspath</code> attribute; (unless 
 *  				using work around way mentioned just above). 
 *  			 </li>
 *  			</ul>
 *  		 </li>
 *  		</ul>
 *  	 </li>
 *  	</ul>
 *  	<br />
 *  </li>
 *  <li>Reminder <b>regarding Ant's <code>&lt;ant&gt;</code> task</b>:<br />
 * 		When Ant's <code>&lt;ant&gt;</code> task is going to be processed, new Ant project is created as you 
 * 		may already know. Here's quote from the <a href="http://ant-contrib.sourceforge.net/tasks/tasks/antfetch_task.html"
 * 		>ant-contrib's <code>&lt;antfetch&gt;</code> task document</a>:
 * 		<blockquote>
 * 		<i>"When the <code>&lt;ant&gt;</code> task is used, in actuality, a new Ant project is created, and 
 * 		depending on the <code>inheritAll</code> property, it is populated with properties from the original 
 * 		project. Then the target in this new project is executed. <b>Any properties set in the new project 
 * 		remain with that project, they do not get "passed back" to the original project</b>. So, for example, 
 * 		if the target in the new project sets a property named "image.directory", there is no reference to 
 * 		that property in the original."</i>
 * 		</blockquote>
 * 		This is somehow important especially for the maven-antrun-plugin environment because you cannot 
 * 		use Ant's <code>&lt;import&gt;</code> task or <code>&lt;include&gt;</code> task under 
 * 		<code>configuration</code> element of the maven-antrun-plugin.<br />
 * 		Hence, <b>if, in a caller target, you like to get property value created during execution of a callee 
 * 		target what is defined in separate Ant build file, then you may use one or both of the following 
 * 		ways</b>: 
 * 		<ul>
 *  	 <li>Use <a href="http://ant-contrib.sourceforge.net/tasks/tasks/antfetch_task.html"
 * 			>ant-contrib's <code>&lt;antfetch&gt;</code> task</a>.
 *  	 </li>
 *  	 <li>In the target being called, define property as rather System property than Ant property.   
 *  	 </li>
 * 		</ul>
 * 		<br />
 * 		As one additional note, this seems to be true too with reference beside property, though I have 
 * 		not further investigated yet. I first thought, since it's reference, making changes on object 
 * 		obtained via the reference in callee target will be naturally reflected back in caller target. 
 * 		But, my experience with the maven-antrun-plugin did not back up my that thought. <br />
 * 		If encountr such situation, then you may use <code>&lt;anttoo&gt;</code> attribute and take 
 * 		the workaround steps described above. Additionally, <a href="https://maven.apache.org/plugins/maven-antrun-plugin/run-mojo.html#exportAntProperties"
 * 		><code>&lt;exportAntProperties&gt;</code></a> option under maven-antrun-plugin's 
 * 		<code>&lt;configuratoin&gt;</code> element is handy to use together. <br />
 * 		Just please be mindful for such situation.<br />
 * 		<br />
 *  </li>
 *  <li><b>To encrypt raw password</b>:<br />
 *  	Happen to know that <u>mvn command line tool seems NOT to be able to parse certain special 
 *  	characters fed at command line</u>. Its cause probably has factor of OS shell. Thereby, result 
 *  	of password encryption with -ep or --encrypt-password option of mvn command line tool may not be 
 *  	right for some cases. (I do not have investigated much, searched filed bug, nor filed a new bug 
 *  	for such issue due to lack of usable time.) <br />
 *    	When the decrypted password with this (<code>&lt;mvnservercreden&gt;</code> Ant task) did not work, 
 *    	then try to dump the decrypted password by using 
 *    	<a href="https://ant.apache.org/manual/Tasks/echoproperties.html"><code>&lt;echoproperty&gt;</code></a> 
 *    	Ant task (with its prefix attribute),  
 *      <a href="https://ant.apache.org/manual/Tasks/echo.html"><code>&lt;echo&gt;</code></a> Ant task, or 
 *      any other way. And check whehter the decrypted (and decorated) password contains the original 
 *      raw password. <br />
 *      If the decrypted one did not match with the orignal one, then encrypt the orignal raw password 
 *      by this (<code>&lt;mvnservercreden&gt;</code> Ant task) like a below example, save encrypted 
 *      password being shown to <code>password</code> element of appropriate server element in your 
 *      Maven user or global settings file, and try again. 
 *  	<blockquote><code>
 *  	&lt;mvnservercreden <br />
 *  	&nbsp;&nbsp;&nbsp;&nbsp;<b>encrypt="true" password="raw_password" </b> /&gt;<br />
 *  	</code></blockquote>
 *  </li>
 *  <li><a id="limitation"><b>Limitation/restriction/prerequisite</b></a><br />
 *  	<ul>
 *  	 <li>This (<code>mvnservercreden</code> Ant task) works Maven ver 3.x but Maven ver 2.x probably 
 *  		(have not tested yet). 
 *  	 </li>
 *  	 <li>The case of using privateKey element and/or passphrase element of server element in 
 *  		Maven settings file is not currently supported.
 *  	 </li>
 *  	 <li>For using <code>mvnservercreden</code> Ant task with maven-antrun-plugin, 
 *  		only with Oracle's JVM (and seemingly OpenJDK JVM (not all versions) and IBM JVM), 
 *  		<code>mvnservercreden</code> Ant task can recognize Maven user settings file specified with 
 *  		-s or --settings option and/or Maven global settings file specified with -gs or 
 *  		--global-settins option of mvn command line tool.
 *  	 </li>
 *  	</ul>
 *  </li>
 * </ul>
 * 
 * <h4><a id="configuration">Configuration</a></h4>
 * <ul>
 *  <li>In the <b>case of using maven-antrun-plugin</b><br />
 *  	<ol>
 *  	 <li>Define com.newmainsoftech:ant-util:jar as a dependency of maven-antrun-plugin:
 *  		<blockquote><code>
 *  		&lt;<b>plugin</b>&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>artifactId</b>&gt;<b>maven-antrun-plugin</b>&lt:/artifactId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;dependencies&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>dependency</b>&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;<b>&lt;groupId&gt;com.newmainsoftech&lt;/groupId&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;artifactId&gt;ant-util&lt;/artifactId&gt;</b><br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;version&gt;#.#.#&lt;/version&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/dependency&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/dependencies&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  		&lt;/plugin&gt;<br />
 *  		</code></blockquote>
 * 		 </li>
 * 		 <li>Define <code>taskdef</code> tag under execution's configuration tag like:<br />
 * 			<blockquote><code>
 *  		&lt;<b>plugin</b>&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>artifactId</b>&gt;<b>maven-antrun-plugin</b>&lt:/artifactId&gt;<br />
 *  		&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;executions&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>execution</b>&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;id&gt;as_you_like&lt;/id&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;phase&gt;as you need&lt;/phase&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;goals&gt;&lt;goal&gt;run&lt;/goal&gt;&lt;/goals&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>configuration</b>&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;target name="what_ever_you_like"&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>taskdef <br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resource="net/sf/antcontrib/antlib.xml" <br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;classpathref="maven.plugin.classpath"</b> /&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- Now you can use mvnservercreden tag --&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;<b>mvnservercreden</b> serverid="test_ds1" /&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/target&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/configuration&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/execution&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;
 * 			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/executions&gt;<br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;...<br />
 *  		&lt;/plugin&gt;<br />
 * 			</code></blockquote>
 * 		 </li>
 * 		</ol>
 *  </li>
 *  <li>If you cannot define com.newmainsoftech:ant-util:jar as a dependency in your project's
 *  	pom.xml, or the case of stand alone Ant environment
 *  	<ol>
 *  	 <li>Define <code>path</code> tag for this project's archive ant-util.jar file and 
 *  		sub-dependencies.<br />
 *  		You need to provide each path of the following components:
 * 			<ul>
 * 			 <li>com.newmainsoftech:ant-util:jar</li>
 * 			  <li>org.apache.maven:maven-settings:jar</li>
 * 			 <li>org.apache.maven:maven-settings-builder:jar</li>
 * 			 <li>org.sonatype.plexus:plexus-cipher:jar</li>
 * 			 <li>org.sonatype.plexus:plexus-sec-dispatcher:jar</li>
 * 			 <li>org.sonatype.aether:aether-api:jar</li>
 * 			 <li>org.sonatype.aether:aether-util:jar</li>
 * 			 <li>org.sonatype.aether:aether-spi:jar</li>
 * 			 <li>org.sonatype.aether:aether-connector-wagon:jar</li>
 * 			</ul>
 * 			(You may do configuration for <code>{@link MavenPath mvnpath}</code> first and 
 * 			use <code>mvnpath</code> to obtain actual path to those binaries.)<br />
 * 			<br />
 * 			Define a <code>path</code> tag with those paths as the alternative of 
 * 			<code>maven.plugin.classpath</code> path reference of the above maven-antrun-plugin example:
 * 				<blockquote><code>
 * 				&lt;<b>path</b> <b>id</b>=&quot;<b>antutil_path</b>&quot; <br />
 * 				&nbsp;&nbsp;&nbsp;&nbsp;path=&quot;${lengthy_path_of_antutil_and_fellows}&quot; /&gt;
 * 				</code></blockquote>
 *  	 </li>
 *  	 <li>Define <code>taskdef</code> tag for the ant-util's antlib.xml<br />
 * 			<blockquote><code>
 * 			&lt;<b>taskdef</b> <br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;<b>resource=&quot;com/newmainsoftech/ant/antlib.xml&quot;</b> <br />
 * 			&nbsp;&nbsp;&nbsp;&nbsp;<b>classpathref</b>=&quot;<b>antutil_path</b>&quot; /&gt;
 * 			</code></blockquote>
 *  	 </li>
 *  	</ol>
 *  </li>
 * </ul>
 * <br />
 * <b>Security Note</b>: be mindful of how to treat log file (or screen output) when you direct Maven or 
 * Ant to dump properties to log file (or screen) during development or test with your own Maven settings 
 * files. Also, please be advised about security risk on credential information stored at property in 
 * memory from  memory scan. However, IMHO, if someone can do memory scan on your machine, then you are 
 * already dead; there will be good possibility of that person has already gotten password to log-in to 
 * your machine (probably by using like pass-the-hash attack) and can also do most likely much worse than 
 * memory scan.<br />
 * 
 * @author Arata Y.
 */
public class MavenServerCredential extends Property {
	private MavenProjectAccessor mavenProjectAccessor = new MavenProjectAccessor();
		protected MavenProjectAccessor getMavenProjectAccessor() {
			return mavenProjectAccessor;
		}
		protected void setMavenProjectAccessor( final MavenProjectAccessor mavenProjectAccessor) {
			this.mavenProjectAccessor = mavenProjectAccessor;
		}
	
	/**
	 * Attribute to specify target server under servers element in settings.xml file. 
	 */
	private String serverId = null;
		public String getServerId() {
			return serverId;
		}
		public void setServerId( final String serverId) {
			if (( serverId != null) && (serverId.trim().length() > 0)) { 
				this.serverId = serverId.trim();
			}
			else {
				throw new IllegalArgumentException( 
						"Value of serverId attribute cannot be either null or empty string but " 
						+ "server ID what can be found under servers element in Maven's " 
						+ "settings.xml file.");
			}
		}
	/*
	 * Attribute to specify name of property where user name will be stored. <br />
	 * Default to [serverId].username (replacing [serverId] part with server ID given to 
	 * <code>{@link #setServerId(String)}</code> method.) 
	 */
	private String userPropName = null;
		/**
		 * Getter of <code>userPropName</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to store user name being used in accessing server specified by 
		 * <code>{@link #setServerId(String)}</code> method.<br />
		 * Default to [serverId].username (replacing [serverId] part with server ID given to 
		 * <code>{@link #setServerId(String)}</code> method.)
		 * 
		 * @return Name of property where user name will be stored.
		 */
		public String getUserPropName() {
			return userPropName;
		}
		/**
		 * Setter of <code>userPropName</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to store user name being used in accessing server specified by 
		 * <code>{@link #setServerId(String)}</code> method.<br />
		 * Default to [serverId].username (replacing [serverId] part with server ID given to 
		 * <code>{@link #setServerId(String)}</code> method.)
		 * 
		 * @param userPropName Name of a property where user name will be stored.
		 */
		public void setUserPropName( final String userPropName) {
			if (( userPropName != null) && (userPropName.trim().length() > 0)) { 
				this.userPropName = userPropName.trim();
			}
			else {
				throw new IllegalArgumentException( 
						"Value of userPropName attribute cannot be either null or empty string.");
			}
		}

	/*
	 * Attribute to specify name of property where password will be stored. <br />
	 * Default to [serverId].password (replacing [serverId] part with server ID given to 
	 * <code>{@link #setServerId(String)}</code> method.) 
	 */
	private String passwordPropName = null;
		/**
		 * Getter of <code>passwordPropName</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to store password being used in accessing server specified by 
		 * <code>{@link #setServerId(String)}</code> method.<br />
		 * Default to [serverId].password (replacing [serverId] part with server ID given to 
		 * <code>{@link #setServerId(String)}</code> method.)
		 * 
		 * @return Name of property where user name will be stored.
		 */
		public String getPasswordPropName() {
			return passwordPropName;
		}
		/**
		 * Setter of <code>passwordPropName</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to store password being used in accessing server specified by 
		 * <code>{@link #setServerId(String)}</code> method.<br />
		 * Default to [serverId].password (replacing [serverId] part with server ID given to 
		 * <code>{@link #setServerId(String)}</code> method.)
		 * 
		 * @param passwordPropName Name of property where user name will be stored.
		 */
		public void setPasswordPropName( final String passwordPropName) {
			if (( passwordPropName != null) && (passwordPropName.trim().length() > 0)) { 
				this.passwordPropName = passwordPropName.trim();
			}
			else {
				throw new IllegalArgumentException( 
						"Value of passwordPropName attribute cannot be either null or empty string.");
			}
		}
	
	/* 
	 * Control switch either decrypt or encrypt.<br />
	 * Default to false.
	 */
	private boolean encrypt = false;
		/**
		 * Return value indicates whether operation will be for decryption (false) or encryption (true).
		 * @return true when operation will be encryption, false for decryption. <br />
		 * Default to false.
		 */
		public boolean isEncrypt() {
			return encrypt;
		}
		/**
		 * Set value of switch controlling type of operation either decrypt (false) or encrypt (true).
		 * @param encrypt
		 */
		public void setEncrypt( boolean encrypt) {
			this.encrypt = encrypt;
		}
	/*
	 * To store password for encryption. <br />
	 * Encrypted value will be saved to property specified by 
	 * <code>{@link #setPasswordPropName(String)}</code> method.   
	 */
	private String password = null;
		/**
		 * @return Password string for encryption.
		 */
		public String getPassword() {
			return password;
		}
		/**
		 * To provide password for encyrption. <br />
		 * When <code>{@link #isEncrypt()}</code> method return true, password set by this will be 
		 * encrypted (and decorated). The encrypted password will be stored to a property when either one 
		 * of below conditions is satisfied in order, otherwise be shown to console as an INFO level log. 
		 * <ol>
		 *  <li>If password property name is specified by <code>{@link #setPasswordPropName(String)}</code> 
		 *  	method, then the encrypted password will be stored to that property.
		 *  </li>
		 *  <li>If name attribute is given value by <code>{@link #setName(String)}</code> method, 
		 *  	then the encrypted password will be stored to ${name}.password property.
		 *  </li>
		 *  <li>If server ID is specified by <code>{@link #setServerId(String)}</code> method, then 
		 *  	the encrypted password will be stored to ${serverId}.password property.
		 *  </li>
		 * </ol>
		 * 
		 * @param password for encryption.
		 */
		public void setPassword( final String password) {
			this.password = password;
		}

	public static final String CmdLineArgsSystemPropName = "sun.java.command";
		/**
		 * @return {@value #CmdLineArgsSystemPropName}
		 */
		public static String getCmdLineArgsSystemPropName() {
			return CmdLineArgsSystemPropName;
		}
	/**
	 * To obtain command line argumeths fed to mvn command line tool, in order to acknowledge whether 
	 * needs to use custom Maven global and/or user settings file(s).<br />
	 * Note: currently this works only with Oracle JVM (and seemingly OpenJDK JVM (not all versions) and 
	 * IBM JVM) because this quotes value of {@value #CmdLineArgsSystemPropName} system property.
	 * 
	 * @return Arguments given to mvn command line tool.<br />
	 */
	public String getMvnCmdLineArgs() {
		return System.getProperty( getCmdLineArgsSystemPropName());
	}
	
	public static final String FileSeparator = System.getProperty( "file.separator");
		public static String getFileSeparator() {
			return FileSeparator;
		}
	/**
	 * @return path of default Maven global settings file (${M2_HOME}/conf/settings.xml). <br /> 
	 * Or null when encounters not anticipated condition.
	 */
	public String getDefaultGlobalSettingsFilePath() {
		MavenPath mavenPath = new MavenPath( this.getProject());
		File m2InstallationDir = mavenPath.getM2InstallationDir();
			if ( m2InstallationDir == null) return null;
		File defaultGlobalSettingsFile 
		= new File( 
				m2InstallationDir, 
				"conf".concat( MavenServerCredential.getFileSeparator()).concat( "settings.xml"));
		return defaultGlobalSettingsFile.getAbsolutePath();
	}
	/*
	 * Attribute to specify path of Maven global settings file.<br />
	 * Default to ${M2_HOME}/conf/settings.xml, or can be null if Maven has not been installed and 
	 * not configured properly (${M2_HOME} does not exist).
	 */
	private String globalSettingsPath = getDefaultGlobalSettingsFilePath(); 
		/**
		 * Getter of <code>globalSettingsPath</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to specify custom Maven global setting file.<br />
		 * 
		 * @return Path of custom Maven global setting file. <br /> 
		 * Default to ${M2_HOME}/conf/settings.xml (or can be null if Maven has not been installed and 
		 * not configured properly; means ${M2_HOME} does not exist).
		 */
		public String getGlobalSettingsPath() {
			return globalSettingsPath;
		}
		/**
		 * Setter of <code>globalSettingsPath</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to specify custom Maven global setting file. <br />
		 * 
		 * @param globalSettingsPath Path of custom Maven global setting file.
		 */
		public void setGlobalSettingsPath( final String globalSettingsPath) {
			if (( globalSettingsPath != null) && (globalSettingsPath.trim().length() > 0)) { 
				this.globalSettingsPath = globalSettingsPath.trim();
			}
			else {
				throw new IllegalArgumentException( 
						"Value of globalSettingsPath attribute cannot be either null or empty string.");
			}
		}
	public static final String MvnCmdGlobalSettingsOptionName = "--global-settings";
		/**
		 * @return {@value #MvnCmdGlobalSettingsOptionName}
		 */
		public static String getMvnCmdGlobalSettingsOptionName() {
			return MvnCmdGlobalSettingsOptionName;
		}
	public static final String MvnCmdGlobalSettingsOptionShortName = "-gs";
		/**
		 * @return {@value #MvnCmdGlobalSettingsOptionShortName}
		 */
		public static String getMvnCmdGlobalSettingsOptionShortName() {
			return MvnCmdGlobalSettingsOptionShortName;
		}
	/*
	 * To specify whether ignoring {@value #MvnCmdUserSettingsOptionShortName}, 
	 * {@value #MvnCmdUserSettingsOptionName}, {@value #MvnCmdGlobalSettingsOptionShortName}, 
	 * or {@value #MvnCmdGlobalSettingsOptionName} mvn command line options. 
	 */
	private boolean ignoreCmdArgs = false;
		public static final String IgnoreCmdArgsPropertyName = "mvnservercreden.ignorecmdargs";
			/**
			 * @return {@value #IgnoreCmdArgsPropertyName}
			 */
			public static String getIgnoreCmdArgsPropertyName() {
				return IgnoreCmdArgsPropertyName;
			}
		/**
		 * Indicate whether ignore {@value #MvnCmdUserSettingsOptionShortName}, 
		 * {@value #MvnCmdUserSettingsOptionName}, {@value #MvnCmdGlobalSettingsOptionShortName}, 
		 * or {@value #MvnCmdGlobalSettingsOptionName} mvn command line options. <br />
		 * This will check next places to decide return value in shown preceding order:
		 * <ol>
		 *  <li><code>{@value #IgnoreCmdArgsPropertyName}</code> Maven property</li>
		 *  <li><code>{@value #IgnoreCmdArgsPropertyName}</code> Ant property</li>
		 *  <li><code>ignorecmdargs</code> attribute</li>
		 * </ol>
		 * 
		 * @return true when {@value #MvnCmdUserSettingsOptionShortName}, 
		 * {@value #MvnCmdUserSettingsOptionName}, {@value #MvnCmdGlobalSettingsOptionShortName}, 
		 * or {@value #MvnCmdGlobalSettingsOptionName} mvn command line options will be ignored.<br />
		 * Default to false.
		 */
		public boolean isIgnoreCmdArgs() {
			// Check mvnservercreden.ignorecmdargs Maven property ---------------------------------
			String ignoreCmdArgsPropStr 
			= getMavenProjectAccessor().getMavenProperty( 
					this, MavenServerCredential.getIgnoreCmdArgsPropertyName());
			if ( ignoreCmdArgsPropStr != null) {
				boolean ignoreCmdArgs = Boolean.parseBoolean( ignoreCmdArgsPropStr);
				setIgnoreCmdArgs( ignoreCmdArgs);
				return ignoreCmdArgs;
			}
			// ------------------------------------------------------------------------------------
			
			// Check mvnservercreden.ignorecmdargs Ant property -----------------------------------
			ignoreCmdArgsPropStr
			= getProject().getProperty( MavenServerCredential.getIgnoreCmdArgsPropertyName());
			if ( ignoreCmdArgsPropStr != null) {
				boolean ignoreCmdArgs = Boolean.parseBoolean( ignoreCmdArgsPropStr);
				setIgnoreCmdArgs( ignoreCmdArgs);
				return ignoreCmdArgs;
			}
			// ------------------------------------------------------------------------------------
			
			return this.ignoreCmdArgs;
		}
		public void setIgnoreCmdArgs( boolean ignoreCmdArgs) {
			this.ignoreCmdArgs = ignoreCmdArgs;
		}
		
	/**
	 * Obatin Maven global settings file. <br />
	 * Where Maven global settings file will be sought at is in next order:
	 * <ol>
	 *  <li>path specified by either {@value #MvnCmdGlobalSettingsOptionName}} or 
	 *  	{@value #MvnCmdGlobalSettingsOptionShortName} options at mvn command line.
	 *  </li>
	 *  <li>path specified by <code>globalSettingsPath</code> attribute (of <code>mvnservercreden</code> 
	 *  Ant task.)
	 *  </li>
	 *  <li>Default location (${M2_HOME}/conf/settings.xml).
	 *  </li>
	 * </ol>
	 * 
	 * @return Maven global settings file.
	 */
	protected File getGlobalSettingsFile() {
		String globalSettingsPath = null;
			if ( !isIgnoreCmdArgs()) {
				int globalSettingsIndex = -1;
				List<String> mvnCmdLineArgsList = null;
				final String mvnCmdLineArgs = getMvnCmdLineArgs();
					if ( mvnCmdLineArgs != null) { // mvn case; not stand-alone Ant target case
						mvnCmdLineArgsList = Arrays.asList( mvnCmdLineArgs.split( "\\s+"));
						for( String mvnCmdLineArg : mvnCmdLineArgsList) {
							if ( mvnCmdLineArg.equals( 
										MavenServerCredential.getMvnCmdGlobalSettingsOptionShortName()) 
									|| mvnCmdLineArg.equals( 
											MavenServerCredential.getMvnCmdGlobalSettingsOptionName())) {
								globalSettingsIndex = mvnCmdLineArgsList.indexOf( mvnCmdLineArg) + 1;
								break; // for
							}
						} // for
					}
				if (( -1 < globalSettingsIndex) && (globalSettingsIndex < mvnCmdLineArgsList.size())) {
					globalSettingsPath = mvnCmdLineArgsList.get( globalSettingsIndex);
				}
			}
			if ( globalSettingsPath == null) {
				globalSettingsPath = getGlobalSettingsPath();
			}
	    File globalSettingsFile = new File( globalSettingsPath);
	    	if ( !globalSettingsFile.exists()) {
	            throw new BuildException(
	            		String.format(
	            				"Could not locate Maven global settings file at %1$s.", 
	            				globalSettingsFile.getPath())
	            		);
	    	}
	    	else if ( !globalSettingsFile.isFile()) {
	            throw new BuildException(
	            		String.format(
	            				"%1$s is not path of Maven global settings file.", 
	            				globalSettingsFile.getPath())
	            		);
	    	}
	    return globalSettingsFile;
	}
		
	/**
	 * ${user.home}/.m2/settings.xml what is path of default Maven user settings file.
	 */
	public final String DefaultUserSettingsFilePath 
	= System.getProperty( "user.home").concat( MavenServerCredential.getFileSeparator())
		.concat( ".m2").concat( MavenServerCredential.getFileSeparator())
		.concat( "settings.xml");
		/**
		 * @return path of default Maven user settings.xml file.
		 */
		public String getDefaultUserSettingsFilePath() {
			return DefaultUserSettingsFilePath;
		}
	/*
	 * Attribute to specify path of Maven user settings file.<br />
	 * Default to ${user.home}/.m2/settings.xml 
	 */
	private String userSettingsPath = getDefaultUserSettingsFilePath(); 
		/**
		 * Getter of <code>userSettingsPath</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to specify custom Maven user setting file.
		 * @return Path of custom Maven user setting file.
		 */
		public String getUserSettingsPath() {
			return userSettingsPath;
		}
		/**
		 * Setter of <code>userSettingsPath</code> attribute of <code>mvnservercreden</code> 
		 * Ant task what is used to specify custom Maven user setting file.
		 * @param userSettingsPath Path of custom Maven user setting file.
		 */
		public void setUserSettingsPath( final String userSettingsPath) {
			if (( userSettingsPath != null) && (userSettingsPath.trim().length() > 0)) { 
				this.userSettingsPath = userSettingsPath.trim();
			}
			else {
				throw new IllegalArgumentException( 
						"Value of userSettingsPath attribute cannot be either null or empty string.");
			}
		}
	public static final String MvnCmdUserSettingsOptionShortName = "-s";
		/**
		 * @return {@value #MvnCmdUserSettingsOptionShortName}
		 */
		public static String getMvnCmdUserSettingsOptionShortName() {
			return MvnCmdUserSettingsOptionShortName;
		}
	public static final String MvnCmdUserSettingsOptionName = "--settings";
		/**
		 * @return {@value #MvnCmdUserSettingsOptionName}
		 */
		public static String getMvnCmdUserSettingsOptionName() {
			return MvnCmdUserSettingsOptionName;
		}
	
	/**
	 * Obatin Maven user settings file. <br />
	 * Where Maven user settings file will be sought at is in next order:
	 * <ol>
	 *  <li>path specified by either {@value #MvnCmdUserSettingsOptionName}} or 
	 *  	{@value #MvnCmdUserSettingsOptionShortName} options at mvn command line.
	 *  </li>
	 *  <li>path specified by <code>userSettingsPath</code> attribute (of <code>mvnservercreden</code> 
	 *  Ant task.)
	 *  </li>
	 *  <li>Default location (${user.home}/.m2/settings.xml).
	 *  </li>
	 * </ol>
	 * 
	 * @return Maven user settings file.
	 */
	protected File getUserSettingsFile() {
	    String userSettingsPath = null;
			if ( !isIgnoreCmdArgs()) {
				int userSettingsIndex = -1;
				List<String> mvnCmdLineArgsList = null;
				final String mvnCmdLineArgs = getMvnCmdLineArgs();
					if ( mvnCmdLineArgs != null) { // mvn case; not stand-alone Ant target case
						mvnCmdLineArgsList = Arrays.asList( mvnCmdLineArgs.split( "\\s+"));
						for( String mvnCmdLineArg : mvnCmdLineArgsList) {
							if ( mvnCmdLineArg.equals( 
										MavenServerCredential.getMvnCmdUserSettingsOptionShortName()) 
									|| mvnCmdLineArg.equals( 
											MavenServerCredential.getMvnCmdUserSettingsOptionName())) {
								userSettingsIndex = mvnCmdLineArgsList.indexOf( mvnCmdLineArg) + 1;
								break; // for
							}
						} // for
					}
				if (( -1 < userSettingsIndex) && (userSettingsIndex < mvnCmdLineArgsList.size())) {
					userSettingsPath = mvnCmdLineArgsList.get( userSettingsIndex);
				}
			}
			if ( userSettingsPath == null) {
		    	userSettingsPath = getUserSettingsPath();
			}
	    
		File userSettingsFile = new File( userSettingsPath);
	    	if ( !userSettingsFile.exists()) {
	            throw new BuildException(
	            		String.format(
	            				"Could not locate Maven user settings file at %1$s.", 
	            				userSettingsFile.getPath())
	            		);
	    	}
	    	else if ( !userSettingsFile.isFile()) {
	            throw new BuildException(
	            		String.format(
	            				"%1$s is not path of Maven user settings file.", 
	            				userSettingsFile.getPath())
	            		);
	    	}
	    return userSettingsFile;
	}
		
	/**
	 * Attribute to switch whether set property as Ant property too additionally to Maven property. 
	 * Default value is true. 
	 */
	private boolean anttoo = true;
		/**
		 * Get {@link #anttoo} attribute value what is switch to controls whether set property as 
		 * Ant property too additionally to Maven property.
		 * @return value of <code>anttoo</code> attribute. 
		 */
		public boolean getAnttoo() {
			return anttoo;
		}
		/**
		 * Set value to {@link #anttoo} attribute what is switch to controls whether set property as 
		 * Ant property too additionally to Maven property.
		 * @param anttoo
		 * @see #addProperty(String, Object)
		 */
		public void setAnttoo( boolean anttoo) {
			this.anttoo = anttoo;
		}
	
	private PlexusCipher plexusCipher;
		{
			try {
				plexusCipher = new DefaultPlexusCipher();
			}
			catch( PlexusCipherException exception) {
	            throw new BuildException( exception);
			}
		}
		public PlexusCipher getPlexusCipher() {
			return plexusCipher;
		}
		public void setPlexusCipher( final PlexusCipher plexusCipher) {
			if ( plexusCipher == null) {
				throw new IllegalArgumentException( 
						"plexusCipher argument value cannot be null.");
			}
			this.plexusCipher = plexusCipher;
		}
		
	/**
	 * Getter of Maven's settings security file (${user.home}/.m2/settings-security.xml).
	 * @return Maven's settings security file (${user.home}/.m2/settings-security.xml)
	 */
	protected File getDefaultSettingsSecurityFile() {
		final String userHomeStr = System.getProperty( "user.home");
		final String fileSeparator = MavenServerCredential.getFileSeparator();
		File settingsSecurityFile
		= new File( 
				userHomeStr.concat( fileSeparator)
				.concat( ".m2").concat( fileSeparator)
				.concat( "settings-security.xml"));
			if ( !settingsSecurityFile.exists()) {
                throw new BuildException( 
                		String.format(
                				"Maven settings security file (%1$s) does not exist.",
                				settingsSecurityFile.getPath()
                				)
                		);
			}
			else if ( !settingsSecurityFile.isFile()) {
                throw new BuildException( 
                		String.format(
                				"%1$s is not Maven settings security file.",
                				settingsSecurityFile.getPath()
                				)
                		);
			}
		return settingsSecurityFile;
	}
	public String getDefaultSettingsSecurityPath() {
		return getDefaultSettingsSecurityFile().getAbsolutePath();
	}
	private String settingsSecurityPath = null;
		public String getSettingsSecurityPath() {
			if ( settingsSecurityPath != null) return settingsSecurityPath;
			
			final String defaultSettingsSecurityPath = getDefaultSettingsSecurityPath();
				setSettingsSecurityPath( defaultSettingsSecurityPath);
			return defaultSettingsSecurityPath;
		}
		public void setSettingsSecurityPath( final String settingsSecurityPath) {
			this.settingsSecurityPath = settingsSecurityPath;
		}
		public File getSettingsSecurityFile() {
			File settingsSecurityFile = new File( getSettingsSecurityPath());
				if ( !settingsSecurityFile.exists()) {
	                throw new BuildException( 
	                		String.format(
	                				"Maven settings security file (%1$s) does not exist.",
	                				settingsSecurityFile.getPath()
	                				)
	                		);
				}
				else if ( !settingsSecurityFile.isFile()) {
	                throw new BuildException( 
	                		String.format(
	                				"%1$s is not Maven settings security file.",
	                				settingsSecurityFile.getPath()
	                				)
	                		);
				}
			return settingsSecurityFile;
		}
		
	/**
	 * Decrypt master password in Maven settings security file.<br />
	 * 
	 * @param settingsSecurityFile Maven settings security file
	 * @return Decrypted master password
	 */
	protected String getMasterPassword( final File settingsSecurityFile) {
		String location
		= System.getProperty( 
			DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, 
			settingsSecurityFile.getPath());
		
		PlexusCipher plexusCipher = getPlexusCipher();
		try {
			SettingsSecurity settingsSecurity = SecUtil.read( location, true);
			String master = settingsSecurity.getMaster();
				master 
				= plexusCipher.decryptDecorated( 
					master, 
					DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION);
			return master;
		}
		catch( Throwable throwable) {
            throw new BuildException( throwable);
		}
	}
	
	/**
	 * Encrypt password. <br />
	 * 
	 * @param rawPassword
	 * @return Encrypted and decorated password.
	 */
	protected String encrypt( final String rawPassword) {
		final File settingsSecurityFile = getSettingsSecurityFile();
		final String passphrase = getMasterPassword( settingsSecurityFile);
	    
		try {
			return getPlexusCipher().encryptAndDecorate( rawPassword, passphrase);
		}
		catch( Exception exception) {
			throw new BuildException( exception);
		}
	}
	
	/**
	 * Encrypt (and decorate) raw password, and either outout to console as an INFO level log or 
	 * store to a property. <br /> 
	 * The encrypted password will be stored to a property when either one of below conditions is 
	 * satisfied in order, otherwise be shown to console as an INFO level log. 
	 * <ol>
	 *  <li>If password property name is specified by <code>{@link #setPasswordPropName(String)}</code> 
	 *  	method, then the encrypted password will be stored to that property.
	 *  </li>
	 *  <li>If name attribute is given value by <code>{@link #setName(String)}</code> method, 
	 *  	then the encrypted password will be stored to ${name}.password property.
	 *  </li>
	 *  <li>If server ID is specified by <code>{@link #setServerId(String)}</code> method, then 
	 *  	the encrypted password will be stored to ${serverId}.password property.
	 *  </li>
	 * </ol>
	 */
	protected void executeEncrypt() {
		final Project project = getProject();
			if ( project == null) {
				throw new IllegalStateException( "project has not been set");
			}
			
		final String password = getPassword();
			if (( password == null) || "".equals( password)) {
	            throw new BuildException( 
	            		"Value of password attribute cannot be null or empty string for encryption mode.");
			}

		String encryptedPassword = encrypt( password);
			
	    String passwordPropName = getPasswordPropName();
	    	if ( passwordPropName == null) {
	    		String propertyName = getName();
	    			if ( propertyName == null) {
	    				String serverId = getServerId();
	    					if ( serverId != null) {
	    	    	    		passwordPropName = serverId.concat( ".password");
	    					}
	    			}
	    			else {
	    	    		passwordPropName = propertyName.concat( ".password");
	    			}
	    	}
	    	
	    if ( passwordPropName == null) {
	    	log( 
	    			String.format(
	    					"Encrypted (and decorated) password : %1$s",
	    					encryptedPassword
	    					), 
	    			LogLevel.INFO.getLevel());
	    }
	    else {
			final Hashtable antProperties = project.getProperties();
			final Properties mavenProperties = getMavenProjectAccessor().getMavenProperties( this);
				if ( (antProperties == null) && (mavenProperties == null)) {
					throw new BuildException(
							String.format( 
									"Neither of Maven properties nor Ant properties are accessible " 
									+ "to save encrypted password to %1$s property.", 
									passwordPropName)
							);
				}
			boolean antto = getAnttoo();
				if ( !antto && (mavenProperties == null)){
					throw new BuildException(
							String.format( 
									"Encrypted password cannot be saved to %1$s property because " 
									+ "Maven properties are not accessible, and anttoo attribute has " 
									+ "not been set true in order to save as Ant property.",
									passwordPropName)
							);
				}
				else if ( antto && (antProperties == null)) {
					log( 
							String.format( 
									"Encrypted password will be saved only to %1$s Maven property " 
									+ "but Ant property, even though antto attribute has been " 
									+ "set to true, since Ant properties are not accessible.", 
									passwordPropName),
							LogLevel.WARN.getLevel());
				}
			
			if (mavenProperties != null) {
		    	if ( mavenProperties.getProperty( passwordPropName) != null) {
		            throw new BuildException( 
		            		String.format(
		            				"%1$s Maven property has been already defined with %2$s value.", 
		            				passwordPropName, 
		            				mavenProperties.getProperty( passwordPropName))
		            		);
		    	}
		    	
		    	mavenProperties.setProperty( passwordPropName, encryptedPassword);
			}
	    	if ( antto && (antProperties != null)) {
	    		if ( antProperties.get( passwordPropName) != null) {
	                throw new BuildException( 
	                		String.format(
	                				"%1$s Ant property has been already defined with %2$s value.", 
	                				passwordPropName, 
	                				antProperties.get( passwordPropName).toString())
	                		);
	    		}
	    		
	    		project.setProperty( passwordPropName, encryptedPassword);
					// Do not use antProperties.put method instead since antProperties is just 
					// clone of actual Ant properites.
	    	}
    	}
	}
	
	/**
	 * Decrypt password.<br />
	 * 
	 * @param encryptedOne
	 * @return Decripted password.
	 */
	protected String decrypt( String encryptedOne) {
		final File settingsSecurityFile = getSettingsSecurityFile();
		final String master = getMasterPassword( settingsSecurityFile);
		try {
			return getPlexusCipher().decryptDecorated( encryptedOne, master);
		}
		catch( Throwable throwable) {
            throw new BuildException( throwable);
		}
	}
	
	/**
	 * Save user name and decrypted password for specified server in Maven settings file to properties.<br /> 
	 * Rules on names of properties to what user name and decrypted password are stored:
	 * <ol>
	 * <li>Use values of <code>userPropName</code> attribute (being given to <code>
	 * {@link #setUserPropName(String)} </code> method) and <code>passwordPropName</code> attribute 
	 * (being given to <code>{@link #setPasswordPropName(String)} </code> method.)
	 * </li>
	 * <li>If either or both of <code>userPropName</code> attribute and <code>passwordPropName</code> 
	 * attribute is not specified, then use value of <code>name</code> attribute as base for not specified 
	 * one; append "<code>.username</code>" for user name and "<code>password</code>" for password to it.
	 * </li>
	 * <li>If <code>name</code> attribute is not specified, then use value of server ID as base for 
	 * not specified one; append "<code>.username</code>" for user name and "<code>password</code>" for 
	 * password to it.
	 * </li>
	 * </ol>
	 * When true has been given to <code>{@link #setAnttoo(boolean)}</code> method, values of user 
	 * name and password are stored as Ant properties. So then, those can be referred in following 
	 * Ant tasks in the same Ant project.
	 */
	protected void executeDecrypt() {
		final Project project = getProject();
			if ( project == null) {
				throw new IllegalStateException( "project has not been set");
			}
			
        final String serverId = getServerId();
	    	if ( serverId == null) {
	            throw new BuildException( 
	            		"Server ID (what can be found under servers element in Maven's settings.xml file) " 
	            		+ "must be provided via the serverId attribute.");
	    	}
	    	
		final Hashtable antProperties = project.getProperties();
		final Properties mavenProperties = getMavenProjectAccessor().getMavenProperties( this);
			if ( (antProperties == null) && (mavenProperties == null)) {
				throw new BuildException(
						String.format( 
								"Neither of Maven properties nor Ant properties are accessible " 
								+ "to save credential information of %1$s server.", 
								serverId)
						);
			}
			boolean antto = getAnttoo();
			if ( !antto && (mavenProperties == null)){
				throw new BuildException(
						String.format( 
								"Credential information for %1$s server could not be saved to " 
								+ "any property because Maven properties are not accessible, " 
								+ "and anttoo attribute has not been set true in order to save " 
								+ "as Ant property.",
								serverId)
						);
			}
			else if ( antto && (antProperties == null)) {
				log( 
						String.format( 
								"Credential information for %1$s server will be saved only to Maven " 
								+ "property but Ant property, even though antto attribute has been " 
								+ "set to true, since Ant properties are not accessible.", 
								serverId),
						LogLevel.WARN.getLevel());
			}
	   
	    String userPropName = getUserPropName();
	    	if ( userPropName == null) {
	    		String propertyName = getName();
	    			if ( propertyName == null) propertyName = serverId;
	    		userPropName = propertyName.concat( ".username");
	    	}
	    	if ( (mavenProperties != null) && (mavenProperties.getProperty( userPropName) != null)) {
	            throw new BuildException( 
	            		String.format(
	            				"%1$s Maven property has been already defined with %2$s value.", 
	            				userPropName, 
	            				mavenProperties.getProperty( userPropName))
	            		);
	    	}
	    	if ( antto && (antProperties != null)) {
	    		if ( antProperties.get( userPropName) != null) {
	                throw new BuildException( 
	                		String.format(
	                				"%1$s Ant property has been already defined with %2$s value.", 
	                				userPropName, 
	                				antProperties.get( userPropName).toString())
	                		);
	    		}
	    	}
	    String passwordPropName = getPasswordPropName();
	    	if ( passwordPropName == null) {
	    		String propertyName = getName();
	    			if ( propertyName == null) propertyName = serverId;
	    		passwordPropName = propertyName.concat( ".password");
	    	}
	    	if ( (mavenProperties != null) && (mavenProperties.getProperty( passwordPropName) != null)) {
	            throw new BuildException( 
	            		String.format(
	            				"%1$s Maven property has been already defined with %2$s value.", 
	            				passwordPropName, 
	            				mavenProperties.getProperty( passwordPropName))
	            		);
	    	}
	    	if ( antto && (antProperties != null)) {
	    		if ( antProperties.get( passwordPropName) != null) {
	                throw new BuildException( 
	                		String.format(
	                				"%1$s Ant property has been already defined with %2$s value.", 
	                				passwordPropName, 
	                				antProperties.get( passwordPropName).toString())
	                		);
	    		}
	    	}
	
		SettingsBuildingRequest settingsBuildingRequest = new DefaultSettingsBuildingRequest();
		    final File globalSettingsFile = getGlobalSettingsFile();
			settingsBuildingRequest.setGlobalSettingsFile( globalSettingsFile);
		    final File userSettingsFile = getUserSettingsFile();
			settingsBuildingRequest.setUserSettingsFile( userSettingsFile);
		SettingsBuilder settingsBuilder = (new DefaultSettingsBuilderFactory()).newInstance();
		SettingsBuildingResult settingsBuildingResult;
			try {
				settingsBuildingResult = settingsBuilder.build( settingsBuildingRequest);
			}
			catch( Throwable throwable) {
	            throw new BuildException( throwable);
			}
		Settings settings  = settingsBuildingResult.getEffectiveSettings();
		
		final Server server = settings.getServer( serverId);
			if ( server == null) {
				throw new BuildException(
						String.format( 
								"Could not locate <server> element for %1$s server in neither of %2$s or " 
								+ "%3$s Maven setting files.", 
								serverId, 
								userSettingsFile.getPath(), 
								globalSettingsFile.getPath())
						);
			}
		final String userName = server.getUsername();
		
		String decriptedPassword = null;
			String encryptedPassword = server.getPassword();
			if ( encryptedPassword != null) {
				decriptedPassword = decrypt( encryptedPassword);
			}
/*			else { // case of pair of privateKey and passphrase 
				final String privateKeyPath = server.getPrivateKey();
					final File privateKeyFile = new File( privateKeyPath);
						if ( !privateKeyFile.isFile()) {
							throw new BuildException(
									String.format(
											"%1$s private key file for %2$s server credential is not " 
											+ "valid as a file.",
											privateKeyPath, 
											server
											)
									);
						}
				passphrase = server.getPassphrase();
					// When passphrase == null, shall I get it from settingsSecurityFile?
				
				// org.codehaus.plexus.util.xml.Xpp3Dom xpp3Dom 
				// = (Xpp3Dom)(server.getConfiguration());
				// Do decription by ssh or other tool
			}
*/
		if ( decriptedPassword != null) {
			if ( userName != null) {
				if ( mavenProperties != null) {
					mavenProperties.setProperty( userPropName, userName);
				}
				if ( antto && (antProperties != null)) {
					project.setProperty( userPropName, userName);
						// Do not use antProperties.put method instead since antProperties is just 
						// clone of actual Ant properites.
				}
			}
			if ( mavenProperties != null) {
				mavenProperties.setProperty( passwordPropName, decriptedPassword);
			}
			if ( antto && (antProperties != null)) {
				project.setProperty( passwordPropName, decriptedPassword);
					// Do not use antProperties.put method instead since antProperties is just 
					// clone of actual Ant properites.
			}
				log( 
						String.format(
								"%n*** Be mindful with handling log if properties are dumped to log since " 
								+ "credential information for %1$s server is now saved to %2$s%3$s. ***%n",
								serverId,
								((userName == null) ? "" : userPropName.concat( " property and ")),
								passwordPropName.concat( " property")
								), 
						LogLevel.WARN.getLevel());
		}
		else {
			log( 
					String.format(
							"Credential information for %1$s server was not found in either Maven global " +
							"settings file or user settings file.",
							serverId
							), 
					LogLevel.WARN.getLevel());
		}
	}
	
	/**
	 * Perform either decryption or encryption of password. <br />
	 * If <code>{@link #isEncrypt()}</code> method returns true, then perform password encryption 
	 * (see {@link #encrypt(String)} method for detail). Otherwise, perform password decryption 
	 * (see {@link #decrypt(String)} method for detail).
	 */
	@Override
	public void execute() throws BuildException {
		if ( isEncrypt()) {
			executeEncrypt();
		}
		else {
			executeDecrypt();
		}
	}
}

//TODO Need to add feature to handle privateKey and passphrase	
